﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;

namespace BIMP
{
    public static class NotificationExtensions
    {
        private static string GetConfigName(Guid listId)
        {
            return listId.ToString().Replace("-", "") + "_RmdConfig";
        }

        public static List<RmdConfiguration> ReadNotifications(this SPList self)
        {
            string configName = GetConfigName(self.ID);
            string configuration = string.Empty;

            //I used the ParentWeb because the SPList object doesn't have a property bag
            SPWeb web = self.ParentWeb;
            if (web.Properties.ContainsKey(configName))
                configuration = self.ParentWeb.Properties[configName];

            if (string.IsNullOrEmpty(configuration))
                return new List<RmdConfiguration>();

            return RmdConfiguration.ReadConfigurations(configuration);
        }

        public static RmdConfiguration GetNotification(this SPList self, Guid id)
        {
            return self.ReadNotifications().FirstOrDefault(cfg => cfg.Id.Equals(id));
        }

        public static void SaveNotifications(this SPList list, List<RmdConfiguration> rmdConfigs)
        {
            string configName = GetConfigName(list.ID);
            string configuration = string.Empty;

            //I used the ParentWeb because the SPList object doesn't have a property bag
            configuration = RmdConfiguration.WriteConfigurations(rmdConfigs);
            SPWeb web = list.ParentWeb;

            if (!web.Properties.ContainsKey(configName))
                web.Properties.Add(configName, configuration);
            else
                web.Properties[configName] = configuration;
            web.Properties.Update();
            web.Update();
        }

        public static void AddNotification(this SPList self, RmdConfiguration cfg)
        {
            List<RmdConfiguration> allReminders = self.RemoveNotification(cfg.Id);
            allReminders.Add(cfg);
            self.SaveNotifications(allReminders);

            cfg.CreateNewJobDefinition();
            //Create Timer JobDefinition and schedule
        }

        public static List<RmdConfiguration> RemoveNotification(this SPList self, Guid ID)
        {
            List<RmdConfiguration> cfgs = self.ReadNotifications();
            if (cfgs == null)
                cfgs = new List<RmdConfiguration>();

            RmdConfiguration foundOutCfg = null;
            foreach (var cfg in cfgs)
                if (cfg.Id.Equals(ID))
                {
                    foundOutCfg = cfg;
                    break;
                }

            if (foundOutCfg != null)
            {
                cfgs.Remove(foundOutCfg);
                //Remove Timer JobDefinition and schedule
                DeleteJobDefinition(foundOutCfg);
            }

            self.SaveNotifications(cfgs);


            return cfgs;
        }

        public static BIMPJobDefinition FindJobDefinition(this RmdConfiguration cfg)
        {
            BIMPJobDefinition ret = null;
            try
            {
                using (SPSite site = new SPSite(cfg.SiteId))
                {
                    var webApp = site.WebApplication;
                    foreach (var jd in webApp.JobDefinitions)
                    {
                        if (!jd.Properties.ContainsKey("BIMP"))
                            continue;

                        BIMPJobDefinition tmp = jd as BIMPJobDefinition;
                        if (tmp == null)
                            continue;

                        RmdConfiguration jobCfg = tmp.Configuration;
                        if (jobCfg.Id.Equals(cfg.Id))
                        {
                            ret = jd as BIMPJobDefinition;
                            break;
                        }
                    }
                }
            }
            catch(Exception exc)
            {
                // log error
            }
            return ret;
        }

        public static void DeleteJobDefinition(this RmdConfiguration cfg)
        {
            using (SPSite site = new SPSite(cfg.SiteId))
            {
                var webApp = site.WebApplication;
                foreach (var jd in webApp.JobDefinitions)
                {
                    if (!jd.Properties.ContainsKey("BIMP"))
                        continue;

                    BIMPJobDefinition tmp = jd as BIMPJobDefinition;
                    if (tmp == null)
                        continue;

                    RmdConfiguration jobCfg = tmp.Configuration;
                    if (jobCfg.Id.Equals(cfg.Id))
                    {
                        jd.Delete();
                        break;
                    }
                }
            }
        }

        public static BIMPJobDefinition CreateNewJobDefinition(this RmdConfiguration cfg)
        {
            BIMPJobDefinition ret = null;
            using (SPSite site = new SPSite(cfg.SiteId))
            {

                // THE ORIGINAL VALUE OF REMOTE ADMINISTRATOR
                var remoteAdministratorAccessDenied =SPWebService.ContentService.RemoteAdministratorAccessDenied;

                try
                {

                    // SET THE REMOTE ADMINISTATOR ACCESS DENIED FALSE
                    //SPWebService.ContentService.RemoteAdministratorAccessDenied = false;
                    // delete the custom timer job if it exists
                    var webApp = Microsoft.SharePoint.Administration.SPWebApplication.Lookup(new Uri(site.Url));

                    foreach (var jd in webApp.JobDefinitions)
                    {
                        if (!jd.Properties.ContainsKey("BIMP"))
                            continue;

                        BIMPJobDefinition tmp = jd as BIMPJobDefinition;
                        if (tmp == null)
                            continue;

                        RmdConfiguration jobCfg = tmp.Configuration;
                        if (jobCfg.Id.Equals(cfg.Id))
                        {
                            jd.Delete();
                            break;
                        }
                    }

                    ret = new BIMPJobDefinition(webApp, cfg);
                    ret.Update();
                }
                finally
                {
                    // SET THE REMOTE ADMINISTATOR ACCESS DENIED BACK WHAT 
                    // IT WAS
                    //SPWebService.ContentService.RemoteAdministratorAccessDenied = remoteAdministratorAccessDenied;
 
                }
            }
            return ret;
        }

        public static string ConcatArray(this string[] source, char delimiter)
        {
            if (source == null || source.Length == 0)
                return string.Empty;

            if (delimiter == null)
                delimiter = ';';

            string ret = string.Empty;
            foreach (var s in source)
                ret += string.Format("{0}{1}", s, delimiter);

            ret.TrimEnd(delimiter);
            return ret;
        }

        public static string GetServerUrl(this SPSite site)
        {
            string port = site.Port.ToString();
            if (port == null || port == "80" || port == "443")
                port = "";
            else
                port = ":" + port;
            string protocol = site.Protocol + "//";

            // *** Figure out the base Url which points at the application's root
            return (protocol + site.HostName + port).TrimEnd('/');
        }
             
        public static string GetDefaultViewServerUrl(this SPList list)
        {
            string tmp = list.DefaultViewUrl;
            if (list.BaseTemplate == SPListTemplateType.UserInformation)
            {
                SPWeb web = list.ParentWeb;
                if (!(web.ServerRelativeUrl == "/"))
                    tmp = web.ServerRelativeUrl + "/_layouts/people.aspx";
                else
                    tmp = web.ServerRelativeUrl + "_layouts/people.aspx";
            }

            return list.ParentWeb.Site.GetServerUrl() + tmp.Replace(" ", "%20");
        }
    }
}
